using System;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using Unity.VisualScripting;
using UnityEngine;
public class WebSocketHelper
{
    private volatile static WebSocketHelper _I;
    public static WebSocketHelper I
    {
        get
        {
            if (_I == null)
            {
                _I = new WebSocketHelper();
            }
            return _I;
        }
    }
    private WebSocketHelper() { }
    private ClientWebSocket ws;
    private Thread dataReceiveThread;
    private bool isDoThread;

    public static NetManager netManager;

    public void Connect(string uriStr)
    {
        try
        {
            ws = new ClientWebSocket();
            isDoThread = true;
            dataReceiveThread = new Thread(ReceiveData)
            {
                IsBackground = true
            };
            var task = ws.ConnectAsync(new Uri(uriStr), CancellationToken.None);
            task.Wait();
            dataReceiveThread.Start(ws);
            if (ws.State == WebSocketState.Open)
            {
                Debug.Log("连接服务器完毕。");
            }
        }
        catch (WebSocketException ex)
        {
            Debug.LogError("连接出错：" + ex.Message);
            Debug.LogError("WebSokcet状态：" + ws.State);
            CloseClientWebSocket();
        }
    }

    private void ReceiveData(object socket)
    {
        ClientWebSocket socketClient = (ClientWebSocket)socket;
        while (isDoThread)
        {
            string data = Receive(socketClient);
            if (data != null)
            {
                netManager.OnMessage(data);
            }
        }
        Debug.Log("接收信息线程结束。");
    }

    private string Receive(ClientWebSocket socket)
    {
        try
        {
            if (socket != null && (socket.State == WebSocketState.Open || socket.State == WebSocketState.CloseSent))
            {
                byte[] arrry = new byte[1024];
                ArraySegment<byte> buffer = new ArraySegment<byte>(arrry);
                var task = socket.ReceiveAsync(buffer, CancellationToken.None);
                task.Wait();
                //仅作状态展示。在客户端发送关闭消息后，服务器会回复确认信息，在收到确认信息后状态便是CloseReceived，这里打印输出。
                Debug.Log("socekt当前状态：" + socket.State);
                //如果是结束消息确认，则返回null，不再解析信息
                if (socket.State == WebSocketState.CloseReceived || task.Result.MessageType == WebSocketMessageType.Close)
                {
                    return null;
                }
                return Encoding.UTF8.GetString(buffer.Array, 0, task.Result.Count);
            }
            else
            {
                return null;
            }
        }
        catch (WebSocketException ex)
        {
            Debug.LogError("接收服务器信息错误：" + ex.Message);
            CloseClientWebSocket();
            return null;
        }
    }

    /// <summary>
    /// 发送消息
    /// </summary>
    /// <param name="content"></param>
    public void Send(string content)
    {
        try
        {
            if (ws != null && (ws.State == WebSocketState.Open || ws.State == WebSocketState.CloseReceived))
            {
                ArraySegment<byte> array = new ArraySegment<byte>(Encoding.UTF8.GetBytes(content));
                var task = ws.SendAsync(array, WebSocketMessageType.Binary, true, CancellationToken.None);
            }
        }
        catch (WebSocketException ex)
        {
            Debug.LogError("向服务器发送信息错误：" + ex.Message);
            CloseClientWebSocket();
        }
    }

    /// <summary>
    /// 关闭ClientWebSocket。
    /// </summary>
    public void CloseClientWebSocket()
    {
        //关闭Socket
        if (ws != null && ws.State == WebSocketState.Open)
        {
            var task = ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
            Debug.Log("如果打印过快，↓下面↓这个socket状态可能为Open，出现Open就多试几次，我们想看的是CloseSent状态。");
            Debug.Log("socekt当前状态：" + ws.State);
            task.Wait();
            Debug.Log("socekt当前状态：" + ws.State);
            Debug.Log("连接已断开。");
        }
        //关闭线程
        if (dataReceiveThread != null && dataReceiveThread.IsAlive)
        {
            isDoThread = false;
            dataReceiveThread = null;
        }
    }
}